home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 1 / your choice.zip / your choice / PRGMMING / VISIONIX / VSTATEU.PAS < prev    next >
Pascal/Delphi Source File  |  1993-12-30  |  9KB  |  344 lines

  1. {
  2. ════════════════════════════════════════════════════════════════════════════
  3.  
  4. Visionix Finite State Machine (VStateu) Unit
  5.    Version 0.7
  6.  Copyright 1991,92,93 Visionix
  7.  ALL RIGHTS RESERVED
  8.  
  9. ────────────────────────────────────────────────────────────────────────────
  10.  
  11.  Revision history in reverse chronological order:
  12.  
  13.  Initials  Date      Comment
  14.  ────────  ────────  ───────────────────────────────────────────────────────
  15.  
  16.  jrt       11/02/93  First logged revision.
  17.  
  18. ════════════════════════════════════════════════════════════════════════════
  19. }
  20.  
  21. (*-
  22.  
  23. [TEXT]
  24.  
  25. <Overview>
  26.  
  27. This unit includes functions to assist in the creation and usage
  28. of finate state machine based programs.  It includes functions to
  29. create state machines, add states to machines, track states, remove
  30. states, and execute state machines.
  31.  
  32. <Interface>
  33.  
  34. -*)
  35.  
  36. Unit VStateu;
  37.  
  38. Interface
  39.  
  40. Uses
  41.  
  42.   VTypesu;
  43.  
  44.  
  45. Const
  46.  
  47.   {------------------------------------------}
  48.   { constant returned by a state to tell the }
  49.   { state machine to stop                    }
  50.   {------------------------------------------}
  51.  
  52.   cstateMachineStop   = -1;
  53.  
  54.   {-----------------------}
  55.   { VStateMachineDo flags }
  56.   {-----------------------}
  57.  
  58.   cSmStopOnEveryState = $0001;      { explicit stop after EVERY state }
  59.  
  60.   {---------------------------------------}
  61.   { debug messages for the debug function }
  62.   {---------------------------------------}
  63.  
  64.   csmdStateMachineStarted = $0001;
  65.   csmdStatePre            = $0002;
  66.   csmdStatePost           = $0003;
  67.   csmdStateMachineStopped = $0004;
  68.  
  69. Type
  70.  
  71.   {---------------------}
  72.   { state function type }
  73.   {---------------------}
  74.  
  75.   TStateFunc = FUNCTION (  StateID : INTEGER;
  76.                            nexus   : POINTER   ) : INTEGER;
  77.  
  78.   {----------------------------}
  79.   { per-state info record type }
  80.   {----------------------------}
  81.  
  82.   TStateName = STRING[40];
  83.  
  84.   TState = RECORD
  85.  
  86.     StateID      : INTEGER;
  87.     StateName    : TStateName;
  88.     StateFunc    : TStateFunc;
  89.  
  90.   END;
  91.  
  92.   PState = ^TState;
  93.  
  94.   {-----------------------------------}
  95.   { state machine debug function type }
  96.   {-----------------------------------}
  97.  
  98.   TStateDebugFunc = FUNCTION ( Msg         : LONGINT;
  99.                                StateID     : INTEGER;
  100.                                StateName   : TStateName;
  101.                                nexus       : POINTER         ) : INTEGER;
  102.  
  103.  
  104.  
  105.   {------------------------}
  106.   { The state machine type }
  107.   {------------------------}
  108.  
  109.   TStateMachine = RECORD
  110.  
  111.     NumStatesAlloc : INTEGER;
  112.     CurNumStates   : INTEGER;
  113.     DebugFunc      : TStateDebugFunc;
  114.     State          : Array[1..1] of TState;
  115.  
  116.   END;
  117.  
  118.   PStateMachine = ^TStateMachine;
  119.  
  120. {────────────────────────────────────────────────────────────────────────────}
  121.  
  122. Function  VStateMachineNew(       Flags          : WORD;
  123.                                   NumStates      : INTEGER ) : PStateMachine;
  124.  
  125. Procedure VStateMachineDispose(   SM             : PStateMachine  );
  126.  
  127.  
  128. Procedure VStateMachineDebug(     SM             : PStateMachine;
  129.                                   DebugFunc      : TStateDebugFunc  );
  130.  
  131.  
  132. Procedure VStateMachineAdd(       SM             : PStateMachine;
  133.                                   StateID        : INTEGER;
  134.                                   StateName      : TStateName;
  135.                                   StateFunc      : TStateFunc     );
  136.  
  137. Function  VStateMachineStart(     SM             : PStateMachine;
  138.                                   Flags          : WORD;
  139.                                   StartStateID   : INTEGER;
  140.                                   Nexus          : POINTER        ) : INTEGER;
  141.  
  142.  
  143. {────────────────────────────────────────────────────────────────────────────}
  144.  
  145. Implementation
  146.  
  147. Function  VStateMachineNew(       Flags          : WORD;
  148.                                   NumStates      : INTEGER ) : PStateMachine;
  149.  
  150. Var
  151.  
  152.   NSM : PStateMachine;
  153.  
  154. BEGIN
  155.  
  156.   GetMem( NSM, SizeOf( TStateMachine ) +
  157.                ( SizeOf(TState) * (NumStates-1) ) );
  158.  
  159.   NSM^.NumStatesAlloc := NumStates;
  160.  
  161.   NSM^.CurNumStates   := 0;
  162.  
  163.   @NSM^.DebugFunc      := NIL;  { !! version 6.0 bug }
  164.  
  165.   VStateMachineNew    := NSM;
  166.  
  167. END;
  168.  
  169. {────────────────────────────────────────────────────────────────────────────}
  170.  
  171. Procedure VStateMachineDispose(   SM             : PStateMachine  );
  172.  
  173. BEGIN
  174.  
  175.   FreeMem( SM, SizeOf( TStateMachine ) +
  176.                ( SizeOf(TState) * (SM^.NumStatesAlloc-1) ) );
  177.  
  178. END;
  179.  
  180. {────────────────────────────────────────────────────────────────────────────}
  181.  
  182. Procedure VStateMachineDebug(     SM             : PStateMachine;
  183.                                   DebugFunc      : TStateDebugFunc  );
  184.  
  185. BEGIN
  186.  
  187.   SM^.DebugFunc := DebugFunc;
  188.  
  189. END;
  190.  
  191. {────────────────────────────────────────────────────────────────────────────}
  192.  
  193. Procedure VStateMachineAdd(       SM             : PStateMachine;
  194.                                   StateID        : INTEGER;
  195.                                   StateName      : TStateName;
  196.                                   StateFunc      : TStateFunc     );
  197.  
  198. Var
  199.  
  200.   Z : INTEGER;
  201.  
  202. BEGIN
  203.  
  204.   If SM^.CurNumStates<SM^.NumStatesAlloc Then
  205.   BEGIN
  206.  
  207.     Inc( SM^.CurNumStates );
  208.  
  209.     Z := SM^.CurNumStates;
  210.  
  211.     SM^.State[Z].StateID   := StateId;
  212.     SM^.State[Z].StateName := StateName;
  213.     SM^.State[Z].StateFunc := StateFunc;
  214.  
  215.   END;
  216.  
  217. END;
  218.  
  219. {────────────────────────────────────────────────────────────────────────────}
  220.  
  221.  
  222. Function  VStateMachineStart(     SM             : PStateMachine;
  223.                                   Flags          : WORD;
  224.                                   StartStateID   : INTEGER;
  225.                                   Nexus          : POINTER        ) : INTEGER;
  226.  
  227. Var
  228.  
  229.   CurStateID  : INTEGER;
  230.   NextStateID : INTEGER;
  231.   Z           : INTEGER;
  232.  
  233. BEGIN
  234.  
  235.   {----------------------------------------------}
  236.   { start off looking for the specified state ID }
  237.   {----------------------------------------------}
  238.  
  239.   NextStateId := StartStateID;
  240.  
  241.   {---------------------------------------------}
  242.   { if a debug proc has been specified, tell it }
  243.   { that we are starting the state machine      }
  244.   {---------------------------------------------}
  245.  
  246.   If @SM^.DebugFunc<>NIL Then
  247.     SM^.DebugFunc( csmdStateMachineStarted,
  248.                    NextStateId,
  249.                   '',
  250.                    Nexus                        );
  251.  
  252.  
  253.   {-----------------------------------------}
  254.   { do the state machine until it says STOP }
  255.   { or stop because the cSMStopOnEveryState }
  256.   { flag is set.                            }
  257.   {-----------------------------------------}
  258.  
  259.   Repeat
  260.  
  261.     {--------------------------}
  262.     { look for the nextStateID }
  263.     { until we find it or we   }
  264.     { checked all the states   }
  265.     {--------------------------}
  266.  
  267.     Z := 1;
  268.  
  269.     While (SM^.State[Z].StateID<>NextStateID) and
  270.           (Z<=SM^.CurNumStates              ) Do
  271.  
  272.       Inc( Z );
  273.  
  274.  
  275.     {------------------------------}
  276.     { Did we find the nextstateID? }
  277.     {------------------------------}
  278.  
  279.     If SM^.State[Z].StateID=NextStateID Then
  280.     BEGIN
  281.  
  282.       {----------------------}
  283.       { yep, go do the state }
  284.       {----------------------}
  285.  
  286.       CurStateID := NextStateID;
  287.  
  288.       {----------------------------------------------}
  289.       { if a debug proc has been set, tell it we are }
  290.       { before   the state                           }
  291.       {----------------------------------------------}
  292.  
  293.       If @SM^.DebugFunc<>NIL Then
  294.         SM^.DebugFunc( csmdStatePre,
  295.                        CurStateId,
  296.                        SM^.State[Z].Statename,
  297.                        Nexus                        );
  298.  
  299.  
  300.       NextStateID := SM^.State[Z].StateFunc( CurStateID, Nexus );
  301.  
  302.       {----------------------------------------------}
  303.       { if a debug proc has been set, tell it we are }
  304.       { after the state                              }
  305.       {----------------------------------------------}
  306.  
  307.       If @SM^.DebugFunc<>NIL Then
  308.         SM^.DebugFunc( csmdStatePost,
  309.                        CurStateId,
  310.                        SM^.State[Z].Statename,
  311.                        Nexus                        );
  312.  
  313.  
  314.  
  315.     END
  316.     ELSE
  317.       NextStateID := cStateMachineStop;
  318.  
  319.   Until (NextStateID=cStateMachineStop  ) or
  320.         (Flags and cSMStopOnEveryState>0);
  321.  
  322.   {----------------------------------------------}
  323.   { if a debug proc has been set, tell it we are }
  324.   { stopping the state machine                   }
  325.   {----------------------------------------------}
  326.  
  327.   If @SM^.DebugFunc<>NIL Then
  328.     SM^.DebugFunc( csmdStateMachineStopped,
  329.                    CurStateId,
  330.                    '',
  331.                    Nexus                        );
  332.  
  333.  
  334.   VStateMachineStart := CurStateId;
  335.  
  336. END;
  337.  
  338. {────────────────────────────────────────────────────────────────────────────}
  339. {────────────────────────────────────────────────────────────────────────────}
  340. {────────────────────────────────────────────────────────────────────────────}
  341.  
  342. BEGIN
  343.  
  344. END.